package com.wechat.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wechat.entity.PaymentDTO;
import com.wechat.entity.PrepayOrder;
import com.wechat.entity.TransactionRecord;
import com.wechat.result.PayResult;
import com.wechat.result.Result;
import com.wechat.service.PrepayOrderService;
import com.wechat.service.TransactionRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.time.LocalDateTime;

@RestController
@RequestMapping("/pay/transactions")
@Slf4j
public class PayController {

    @Autowired
    private PrepayOrderService prepayOrderService;
    @Autowired
    private TransactionRecordService transactionRecordService;
    /**
     * 模拟微信支付后端返回预支付交易标识
     * 商家后端发送post请求，请求体中携带的是封装的JSONObject对象，包含金额、商家号、订单号、appid、订单描述、下单微信用户的openid、通知地址
     * @return
     */
    @PostMapping("/jsapi")
    public PayResult jsapi(@RequestBody JSONObject body){
        log.info("模拟微信预支付交易{}",body);//{"amount":{"total":1,"currency":"CNY"},"mchid":"123456","out_trade_no":"1733894836304","appid":"wx*********","description":"外卖订单","notify_url":"http://localhost:8080/notify/paySuccess","payer":{"openid":"*******"}}
        //将该预支付单加入数据库
        PrepayOrder prepayOrder = new PrepayOrder();
        prepayOrder.setAppid(body.getString("appid"));
        prepayOrder.setMchid(body.getString("mchid"));
        prepayOrder.setDescription(body.getString("description"));
        prepayOrder.setNotifyUrl(body.getString("notify_url"));
        prepayOrder.setOutTradeNo(body.getString("out_trade_no"));
        prepayOrder.setOpenid(body.getJSONObject("payer").getString("openid"));
        prepayOrder.setTotal(body.getJSONObject("amount").getBigDecimal("total"));
        prepayOrder.setCurrency(body.getJSONObject("amount").getString("currency"));
        prepayOrder.setCreateTime(LocalDateTime.now());
        prepayOrderService.save(prepayOrder);
        return new PayResult(prepayOrder.getId(),"SUCCESS");
    }

    /**
     * 小程序用户发起微信支付
     * 模拟微信支付后端服务
     * 支付成功后通知商家后端
     * @return
     */
    @PostMapping("/payment")
    public Result payment(@RequestBody PaymentDTO paymentDTO) throws IOException {
        log.info("模拟微信正式支付交易{}",paymentDTO);
        //根据预支付订单id获取商户系统订单号
        PrepayOrder prepayOrder = prepayOrderService.getById(paymentDTO.getPrepayId());
        //如果该预支付订单查不到，则返回错误信息
        if(prepayOrder == null){
            return Result.error("支付失败");
        } else {
            //获取客户端向商户后端发送通知
            CloseableHttpClient httpClient = HttpClients.createDefault();
            String outTradeNo = prepayOrder.getOutTradeNo();
            //生成支付记录
            TransactionRecord transactionRecord = new TransactionRecord();
            BeanUtils.copyProperties(prepayOrder, transactionRecord);
            transactionRecord.setStatus(TransactionRecord.NORMAL);
            transactionRecordService.save(transactionRecord);
            //删除预支付订单
            prepayOrderService.removeById(prepayOrder);
            //支付成功，向商家后端推送结果
            HttpPost httpPost = new HttpPost(prepayOrder.getNotifyUrl());
            httpPost.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
            httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("out_trade_no", outTradeNo);
            jsonObject.put("transaction_id", transactionRecord.getId());
            httpPost.setEntity(new StringEntity(jsonObject.toJSONString(), "UTF-8"));
            httpClient.execute(httpPost);

            //给小程序返回结果
            return Result.success("支付成功");
        }

    }

    /**
     * 模拟关闭预支付单，防止取消用户又付款
     * @param outTradeNo
     * @return
     */
    @PostMapping("/out-trade-no/{outTradeNo}/close")
    public Result close(@PathVariable String outTradeNo, @RequestBody JSONObject body){
        //移除改订单号的预支付订单
        LambdaQueryWrapper<PrepayOrder> wrapper = new LambdaQueryWrapper<PrepayOrder>()
                .eq(PrepayOrder::getOutTradeNo, outTradeNo)
                .eq(PrepayOrder::getMchid, body.getString("mchid"));
        prepayOrderService.remove(wrapper);
        return Result.success();
    }
}
